"""
任务 房价价格预测

"""
import numpy as np
import pandas as pd
from my_utils import *
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import OneHotEncoder,MinMaxScaler
import matplotlib.pyplot as plt
import numpy as py

DATA_FILE = ".\data\house_data.csv"

# 使用的特征列
"""
bedrooms:房间个数  bathrooms:卫生间个数 sqft_living:居住平米数 sqft_lot:总平米数
sqft_above: 上层平米数 sqft_basement: 底层平米数
"""
# 数值型特征值
NUMBER_FEAT_COLS = ['sqft_living','sqft_above','sqft_basement','long','lat']
# 需要独热编码  目前这个列 不是0 就是 1
CATEGORY_FEAT_COLS=['waterfront']

def plot_fitting_line(linear_reg_model, X, y, feat):
    """
    绘制线性回归线
    :param linear_reg_model:
    :param X:
    :param y:
    :param feat:
    :return:
    """
    w = linear_reg_model.coef_
    b = linear_reg_model.intercept_
    plt.figure(figsize=(20,8),dpi=100)
    # 散点图 样本点
    plt.scatter(X, y,alpha=0.5)

    #直线
    plt.plot(X, w * X + b, c='red')
    plt.title(feat)
    plt.show()


def process_features(X_train, X_test):
    """
        特征预处理
    :param X_train:
    :param X_test:
    :return:
    """
    # 1 对类别类型做 one-hot encoding 独热编码
    # encoder = OneHotEncoder(sparse=False)
    encoder = OneHotEncoder(sparse_output=False)
    encoded_tr_feat = encoder.fit_transform(X_train[CATEGORY_FEAT_COLS])
    encoded_te_feat = encoder.transform(X_test[CATEGORY_FEAT_COLS])

    # 2 归一化
    scaler = MinMaxScaler()
    scaled_tr_feat = scaler.fit_transform(X_train[NUMBER_FEAT_COLS])
    scaled_te_feat = scaler.transform(X_test[NUMBER_FEAT_COLS])

    # 横向合并
    X_train_proc = np.hstack((encoded_tr_feat,scaled_tr_feat))
    X_test_proc = np.hstack((encoded_te_feat,scaled_te_feat))
    return X_train_proc, X_test_proc

def main():
    house_data = pd.read_csv(DATA_FILE, usecols=NUMBER_FEAT_COLS + CATEGORY_FEAT_COLS + ['price'])
    X = house_data[NUMBER_FEAT_COLS + CATEGORY_FEAT_COLS]
    y = house_data['price']
    # 分割数据集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1 / 3, random_state=10)
    # 建立线性回归模型
    linear_reg_model = LinearRegression()
    # 模型训练
    linear_reg_model.fit(X_train, y_train)
    # 验证模型
    r2_score = linear_reg_model.score(X_test, y_test)
    print('没做特征处理>>模型的R2值', r2_score) # 0.6268
    # 数据预处理
    X_train_proc,X_test_proc = process_features(X_train,X_test)
    # 建立线性回归模型
    linear_reg_model2 = LinearRegression()
    # 模型训练
    linear_reg_model2.fit(X_train_proc, y_train)
    # 验证模型
    r2_score2 = linear_reg_model2.score(X_test_proc, y_test)
    print('做特征处理后>>模型的R2值', r2_score2)  #0.6272818527724011
    print("模型提升了{:.2f}%".format((r2_score2 -r2_score)/r2_score * 100)) # 0.07%
if __name__ =='__main__':
    main()